package com.flywound.shiro;

import com.flywound.constants.Constant;
import com.flywound.exception.BusinessException;
import com.flywound.exception.code.BaseRespMsgEnum;
import com.flywound.service.RedisService;
import com.flywound.utils.JwtTokenUtil;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
import org.springframework.beans.factory.annotation.Autowired;

import java.util.concurrent.TimeUnit;

public class CustomHashedCredentialsMatcher extends SimpleCredentialsMatcher {

    @Autowired
    private RedisService redisService;

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        JwtToken jwtToken = (JwtToken) token;
        String accessToken = (String) jwtToken.getPrincipal();
        String userId = JwtTokenUtil.getUserId(accessToken);
        //校验账户锁定
        if (redisService.hasKey(Constant.ACCOUNT_LOCK_KEY + userId)) {
            throw new BusinessException(BaseRespMsgEnum.ACCOUNT_LOCK_ERROR);
        }
        //校验账户是否被删除
        if (redisService.hasKey(Constant.DELETED_USER_KEY + userId)) {
            throw new BusinessException(BaseRespMsgEnum.ACCOUNT_ERROR);
        }
        //校验账户是否在黑名单
        if (redisService.hasKey(Constant.JWT_REFRESH_TOKEN_BLACKLIST + accessToken)) {
            throw new BusinessException(BaseRespMsgEnum.TOKEN_ERROR);
        }

        if (redisService.hasKey(Constant.JWT_REFRESH_STATUS + accessToken)) {
            return true;
        }
        //校验Token是否过期
        if (JwtTokenUtil.isTokenExpired(accessToken)) {
            throw new BusinessException(BaseRespMsgEnum.TOKEN_PAST_DUE);
        }

        if (redisService.hasKey(Constant.JWT_REFRESH_KEY + userId)
                && redisService.getExpire(Constant.JWT_REFRESH_KEY + userId, TimeUnit.MILLISECONDS) > JwtTokenUtil.getRemainingTime(accessToken)) {

            //如果没有新的token,则提示Token超时
            if (!redisService.hasKey(Constant.JWT_REFRESH_IDENTIFICATION + accessToken)) {
                throw new BusinessException(BaseRespMsgEnum.TOKEN_PAST_DUE);
            }
        }
        return true;
    }
}
